﻿import { Directive, Input, forwardRef } from '@angular/core';
import { AbstractControl, NG_VALIDATORS, Validator } from '@angular/forms';

@Directive({
  selector: '[requireDigit],[requireLowercase],[requireNonAlphanumeric],[requireUppercase],[requiredLength]',
  providers: [
    { provide: NG_VALIDATORS, useExisting: forwardRef(() => PasswordComplexityValidator), multi: true }
  ]
})
export class PasswordComplexityValidator implements Validator {

  @Input('requireDigit') requireDigit: boolean;
  @Input('requireUppercase') requireUppercase: boolean;
  @Input('requireLowercase') requireLowercase: boolean;
  @Input('requireNonAlphanumeric') requireNonAlphanumeric: boolean;
  @Input('requiredLength') requiredLength: number;

  validate(control: AbstractControl): { [key: string]: any } {
    const givenPassword = control.value;
    let validationResult = null;

    const requireDigit = this.requireDigit;
    if (requireDigit && givenPassword && !/[0-9]/.test(givenPassword)) {
      validationResult = validationResult || {};
      validationResult.requireDigit = true;
    }

    const requireUppercase = this.requireUppercase;
    if (requireUppercase && givenPassword && !/[A-Z]/.test(givenPassword)) {
      validationResult = validationResult || {};
      validationResult.requireUppercase = true;
    }

    const requireLowercase = this.requireLowercase;
    if (requireLowercase && givenPassword && !/[a-z]/.test(givenPassword)) {
      validationResult = validationResult || {};
      validationResult.requireLowercase = true;
    }

    const requiredLength = this.requiredLength;
    if (requiredLength && givenPassword && givenPassword.length < requiredLength) {
      validationResult = validationResult || {};
      validationResult.requiredLength = true;
    }

    // use upperCaseLetters
    const requireNonAlphanumeric = this.requireNonAlphanumeric;
    if (requireNonAlphanumeric && givenPassword && /^[0-9a-zA-Z]+$/.test(givenPassword)) {
      validationResult = validationResult || {};
      validationResult.requireNonAlphanumeric = true;
    }

    return validationResult;
  }
}
